﻿using Autofac;
using Autofac.Extensions.DependencyInjection;
using Common.Config;
using Common.Jwt;
using Common.Result;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using Model.Entitys;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using SqlSugar;
using StackExchange.Redis;
using System.Configuration;
using System.Text;
using System.Text.Json;
using TakeawayWebApi.Controllers.Filter;

namespace TakeawayWebApi.Config
{
    /// <summary>
    /// 扩展类
    /// </summary>
    public static class HostBuilderExtend
    {
        public static void Register(this WebApplicationBuilder builder)
        {
            //注册日志服务
            builder.Logging.AddLog4Net(builder.Configuration["log4netPath"]);


            builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
            builder.Host.ConfigureContainer<ContainerBuilder>(container =>
            {
                #region 注册sqlsugar
                container.Register<ISqlSugarClient>(context =>
                {
                    SqlSugarClient db = new (new ConnectionConfig()
                    {
                        ConnectionString = builder.Configuration["SqlServerConn"],//连接符字串
                        DbType = DbType.SqlServer,//数据库类型
                        IsAutoCloseConnection = true,
                        ConfigureExternalServices = new ConfigureExternalServices()
                        {
                            EntityService = (x, p) => //处理列名
                            {
                                p.DbColumnName = UtilMethods.ToUnderLine(p.DbColumnName);//ToUnderLine驼峰转下划线方法
                            },
                            EntityNameService = (x, p) => //处理表名
                            {
                                p.DbTableName = UtilMethods.ToUnderLine(p.DbTableName);//ToUnderLine驼峰转下划线方法
                            }
                        },
                    }, db =>
                    {
                        db.Aop.OnLogExecuting = (sql, pars) =>
                        {
                            //Console.WriteLine(sql);//输出sql
                            Console.WriteLine("\r\n");
                            Console.WriteLine($"{DateTime.Now:yyyyMMdd HH:mm:ss}" + UtilMethods.GetNativeSql(sql, pars));

                        };
                        db.Aop.OnError = (exp) =>
                        {
                            Console.WriteLine("\r\n");
                            Console.WriteLine($"错误sql:{exp.Sql}");
                            //Console.WriteLine($"错误参数:{exp.Parametres}");
                        };
                        //全局数据过滤器  过滤已删除数据
                        db.QueryFilter.AddTableFilter<AddressBook>(it => it.IsDeleted == 0)
                                      .AddTableFilter<Dish>(it => it.IsDeleted == 0)
                                      .AddTableFilter<DishFlavor>(it => it.IsDeleted == 0)
                                      .AddTableFilter<Setmeal>(it => it.IsDeleted == 0)
                                      .AddTableFilter<SetmealDish>(it => it.IsDeleted == 0);
                    });
                    return db;
                });
                #endregion

                //注册接口和实现层
                container.RegisterModule(new AutofacModuleRegister());

                //注册redis
                container.Register<IConnectionMultiplexer>(sp =>
                {
                    var configuration = ConfigurationOptions.Parse(builder.Configuration["RedisConn"]);
                    return ConnectionMultiplexer.Connect(configuration);
                });
            });
            #region JWT鉴权
            //第一步，注册JWT
            builder.Services.Configure<JWTTokenOptions>(builder.Configuration.GetSection("JWTTokenOptions"));
            //第二步，增加鉴权逻辑
            JWTTokenOptions tokenOptions = new JWTTokenOptions();
            builder.Configuration.Bind("JWTTokenOptions", tokenOptions);
            builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)//Scheme
             .AddJwtBearer(options =>  //这里是配置的鉴权的逻辑
             {
                 options.TokenValidationParameters = new TokenValidationParameters
                 {
                     //JWT有一些默认的属性，就是给鉴权时就可以筛选了
                     ValidateIssuer = true,//是否验证Issuer
                     ValidateAudience = true,//是否验证Audience
                     ValidateLifetime = true,//是否验证失效时间
                     ValidateIssuerSigningKey = true,//是否验证SecurityKey
                     ValidAudience = tokenOptions.Audience,//
                     ValidIssuer = tokenOptions.Issuer,//Issuer，这两项和前面签发jwt的设置一致
                     IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(tokenOptions.SecurityKey))//拿到SecurityKey 
                 };

                 // 配置JWT认证失败后返回自定义的结果类同时返回200状态码
                 options.Events = new JwtBearerEvents
                 {
                     OnChallenge = context =>
                     {
                         //此处代码为终止.Net Core默认的返回类型和数据结果
                         context.HandleResponse();
                         //处理浏览器跨域报错问题
                         context.Response.Headers.Add("Access-Control-Allow-Origin", "http://localhost:8080");
                         context.Response.ContentType = "application/json";
                         context.Response.StatusCode = StatusCodes.Status200OK;
                         var result = ResultHelper.Error("NOTLOGIN");
                         //context.Response.WriteAsync(JsonConvert.SerializeObject(result, serializerSettings));
                         context.Response.WriteAsync(JsonConvert.SerializeObject(result, new JsonSerializerSettings
                         {
                             //序列化 result 类的属性转换成首字母小写
                             ContractResolver = new DefaultContractResolver
                             {
                                 NamingStrategy = new CamelCaseNamingStrategy()
                             }
                         }));
                         return Task.CompletedTask;
                     }
                 };
             });
            #endregion

            //Automapper映射
            builder.Services.AddAutoMapper(typeof(AutoMapperConfigs));

            //添加跨域策略
            builder.Services.AddCors(options =>
            {
                options.AddPolicy("CorsPolicy", opt =>
                opt.WithOrigins("http://localhost:8080")
                .AllowAnyHeader()
                .AllowAnyMethod()
                //.WithExposedHeaders("X-Pagination")
                );
            });

            builder.Services.AddControllers(options =>
            {
                //注入异常过滤器
                //options.Filters.Add<CustomerExceptionFilter>();
                options.Filters.Add(typeof(CustomerExceptionFilter));
            }
            ).AddNewtonsoftJson(options =>
            {
                //忽略循环引用
                options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;

                ////设置Json返回的日期格式
                options.SerializerSettings.DateFormatString = "yyyy-MM-dd HH:mm:ss";

                //不改变字段大小
                //options.SerializerSettings.ContractResolver = new DefaultContractResolver();
            });
        }
    }
}
